;MACROS:

%macro sendmessage 1-2
mov byte[_msg+%1],%2
%endmacro

%macro ifreg 1-2
cmp %1,%2
je .execute
jmp .no_execute
.execute:
%endmacro

%macro ifbe 1-2
cmp byte[%1],%2
je .execute
jmp .no_execute
.execute:
%endmacro

%macro else 0
jmp .null_exec
.no_execute:
%endmacro

%macro endife 0
.null_exec:
%endmacro

%macro ifwe 1-2
cmp word[%1],%2
je .execute
jmp .no_execute
.execute
%endmacro

%macro endif 0
.no_execute:
%endmacro

%macro wait 1
mov ax,%1
call hang
%endmacro

%macro putc 1
mov al,%1
call putchar
%endmacro

%macro setb 1
mov byte[%1],1
%endmacro

%macro clearb 1
mov byte[%1],0
%endmacro

%macro printf 1
mov si,%1
call print
%endmacro

%macro setcur 1-2
mov dh,%1
mov dl,%2
call setcursor
%endmacro

%macro cmpstr 1-3
mov si,%1
mov di,%2
mov cx,%3
call compare
%endmacro

%macro line 1
mov cx,%1
call nline
%endmacro


%macro getparam 1
mov si,buffer
add si,%1
call b16num
%endmacro


%macro store_state 1
mov word[%1],ax
mov word[%1+2],bx
mov word[%1+4],cx
mov word[%1+6],dx
mov word[%1+8],si
mov word[%1+10],sp
%endmacro

%macro get_state 1
mov ax,word[%1]
mov bx,word[%1+2]
mov cx,word[%1+4]
mov dx,word[%1+6]
mov si,word[%1+8]
mov sp,word[%1+10]
%endmacro


org 100h
init_code:
push cs
pop ds
mov ax,3
int 0x10

in 	al,0x21
and al,00000000b
out 0x21,al

in 	al,0xa1
and	al,00000000b
out 0xa1,al

mov byte[intr],0x1c
mov si,_scheduler
call set_interrupt

cli

mov al,0x36
out 0x43,al
mov al,0x00
out 0x40,al
mov al,0x10
out 0x40,al

sti

_load_tasks:
_load_btsk:
mov sp,0xf600
pushf
push cs
push _btsk
mov word[btsk_state+10],sp
_load_debug:
mov sp,0xf800
pushf
push cs
push _debug
mov word[debug_state+10],sp
_load_main:
mov sp,0xffff
pushf
push cs
push _main
mov word[main_state+10],sp
_dispatch_main:
ret



_main:
printf pmk

mov ax,0       
mov es,ax
mov ax,0x10    
mov bl,4h       
mul bl          
mov bx,ax
mov dx,word[es:bx]
add bx,2        
mov ax,word[es:bx]

pushf
push cs
push rfint
pushf
push ax
push dx
iret


rfint:
_cmdprompt:
line 1
mov si,buffer
mov cx,255
call clearbuffer
printf msg
call takeinput

analyze:
cmpstr buffer,exit,4
jne next1
jmp exit2dos

next1:
cmpstr buffer,clear_p,9
jne next2
call clear_program
jmp _cmdprompt

next2: 
cmpstr buffer,p_new,6
jne next3
call create_space
jmp _cmdprompt

next3: 
cmpstr buffer,prog_cnt,4
jne next4
call end_sp
jmp _cmdprompt

next4:
cmpstr buffer,setport,5
jne next5
call set_port
jmp _cmdprompt

next5:
cmpstr buffer,outp,5
jne next6
call out_port
jmp _cmdprompt


next6:
cmpstr buffer,dispmem,10
jne next7
call dislmem
jmp _cmdprompt


next7:
cmpstr buffer,dispprog,15
jne next8
call displayprogram
jmp _cmdprompt

next8:
cmpstr buffer,help,4
jne next9
line 1
mov si,startcmd
mov cx,endcmd-startcmd
call printlim
jmp _cmdprompt

next9:
cmpstr buffer,exec,8
jne next10
sendmessage 1,1
jmp _cmdprompt


next10:
cmpstr buffer,clear_data,10
jne next11
mov si,data_buffer
mov cx,256
call clearbuffer
jmp _cmdprompt

next11:
cmpstr buffer,in_port,8
jne next12
call inport
jmp _cmdprompt


next12:
cmpstr buffer,dispdata,12
jne next13
call displaydata
jmp _cmdprompt

next13:
cmpstr buffer,debugcmd,5
jne next14
getparam 6
add cl,0xf0
sendmessage 2,cl
jmp _cmdprompt


next14:
cmpstr buffer,gotoc,5
jne next15
call goto_addr
jmp _cmdprompt

next15:
cmpstr buffer,sttt,13
jne next16
call set_task_time
jmp _cmdprompt

next16:

line 1
printf err
jmp _cmdprompt
exit2dos:
line 1
cli
call reset_pic
mov ax,4c00h
int 0x21


 





set_task_time:
mov si,buffer
getparam 14
cmp cx,0
jne .next1
line 1
printf t0
call clear_input_buffer
call takeinput
mov si,buffer
getparam 0
mov word[main_state+12],cx
jmp end_set
.next1:
cmp cx,1
jne .next2
line 1
printf t1
call clear_input_buffer
call takeinput
mov si,buffer
getparam 0
mov word[btsk_state+12],cx
jmp end_set
.next2:
cmp cx,2
jne .next3
line 1
printf t2
call clear_input_buffer
call takeinput
mov si,buffer
getparam 0
mov word[debug_state+12],cx
jmp end_set
.next3:
line 1
printf sterr
end_set:
ret

clear_input_buffer:
mov si,buffer
mov cx,0xff
call clearbuffer
ret


displaydata:
getparam 13
mov ax,data_buffer
mov word[start_offset],ax
add ax,cx
mov word[end_offset],ax
line 1
printf dmem
call memd
ret





displayprogram:
getparam 16
mov ax,program_buffer
mov word[start_offset],ax
add ax,cx
mov word[end_offset],ax
line 1
printf pmem
call memd
ret



dislmem:
line 1
printf mems
getparam 11
mov word[start_offset],cx
getparam 17
mov word[end_offset],cx 
memd:
mov si,word[start_offset]
disploop:
line 1
mov ax,si
call print_num_hex
putc 0x3a
mov ax,0
mov al,byte[si]
call print_num_hex
inc si
cmp si,word[end_offset]
jna disploop
ret



clear_program:
mov si,program_buffer
mov cx,1024
call clearbuffer
mov si,data_buffer
mov cx,256
call clearbuffer
ret

create_space:
mov si,buffer
add si,7
call b16num
cmp cx,1024
jl cont
jmp errorsp
cont:
mov si,program_buffer
add si,cx
mov word[program_loc],si
jmp end_sp
errorsp:
line 1
printf errsp
end_sp:
line 1
printf pat
mov ax,word[program_loc]
call print_num_hex
ret




set_port:
mov si,word[program_loc]
mov byte[si],100
inc word[program_loc]
getparam 6
mov si,word[program_loc]
mov word[si],cx
add word[program_loc],2
ret

out_port:
mov si,word[program_loc]
mov byte[si],200
inc word[program_loc]
getparam 6
mov si,word[program_loc]
mov word[si],cx
add word[program_loc],2
ret
 
inport:
mov si,word[program_loc]
mov byte[si],190
inc word[program_loc]
getparam 9
mov si,word[program_loc]
mov word[si],cx
add word[program_loc],2
ret


goto_addr:
mov si,word[program_loc]
mov byte[si],50
inc word[program_loc]
getparam 6
mov si,word[program_loc]
mov word[si],cx
add word[program_loc],2
ret









_btsk:
cmp byte[_msg+1],0x1
jne _btsk
_btsk_run:
line 1
printf ep
sendmessage 1,0xff
mov si,program_buffer
decode:
_setport:
ifbe si,100
inc si
mov ax,word[si]
mov word[cur_port],ax
add si,2
jmp decode
endif
_outport:
ifbe si,200
inc si
mov ax,word[si]
mov dx,word[cur_port]
out dx,al
add si,2
jmp decode
endif
_inport:
ifbe si,190
inc si
mov ax,word[si]
push si
mov si,data_buffer
add si,ax
mov dx,word[cur_port]
in al,dx
mov byte[si],al
pop si
add si,2
jmp decode
endif
line 1
printf pt
sendmessage 1,0
jmp _btsk















_debug:
cmp byte[_msg+2],0
je _debug
_mainregdisp:
ifbe _msg+2,0xf0
line 1
printf axd
mov ax,word[main_state]
call print_num_hex
line 1
printf bxd
mov ax,word[main_state+2]
call print_num_hex
line 1
printf cxd
mov ax,word[main_state+4]
call print_num_hex
line 1
printf dxd
mov ax,word[main_state+6]
call print_num_hex
line 1
printf sid
mov ax,word[main_state+8]
call print_num_hex
line 1
printf spd
mov ax,word[main_state+10]
call print_num_hex
line 1
printf ttime
mov ax,word[main_state+12]
mov bx,55
mul bx
call print_num
printf ttime_suf
endif
_btskregdisp:
ifbe _msg+2,0xf1
line 1
printf axd
mov ax,word[btsk_state]
call print_num_hex
line 1
printf bxd
mov ax,word[btsk_state+2]
call print_num_hex
line 1
printf cxd
mov ax,word[btsk_state+4]
call print_num_hex
line 1
printf dxd
mov ax,word[btsk_state+6]
call print_num_hex
line 1
printf sid
mov ax,word[btsk_state+8]
call print_num_hex
line 1
printf spd
mov ax,word[btsk_state+10]
call print_num_hex
line 1
printf ttime
mov ax,word[btsk_state+12]
mov bx,55
mul bx
call print_num
printf ttime_suf
endif
sendmessage 2,0
jmp _debug









_scheduler:
cmp byte[task_time],0
jne .decrem
mov al,byte[clk]
add al,0x30
call put_text_mem
jmp _switch
.decrem:
dec byte[task_time]
iret


_switch:
_swbtsk:
ifbe clk,1
store_state main_state
get_state btsk_state
pusha
mov ax,word[btsk_state+12]
mov word[task_time],ax
popa
endif
_swdebug:
ifbe clk,2
store_state btsk_state
get_state debug_state
pusha
mov ax,word[debug_state+12]
mov word[task_time],ax
popa
endif
_swmain:
ifbe clk,3
store_state debug_state
get_state main_state
pusha
mov ax,word[main_state+12]
mov word[task_time],ax
popa
mov byte[clk],0
endif
pusha
call reset_pic
popa
inc byte[clk]
iret








routines_8086_bios: 

put_text_mem:
mov cx,0b800h
mov es,cx
mov di,158
stosb
ret

compare:
push ds
pop es
cld
rep cmpsb
ret

nline:
endl:
mov al,13
call putchar
mov al,10
call putchar
loop endl
ret

printlim:
printlp:
lodsb
call putchar
loop printlp
ret
 
takeinput:
mov byte[inputlength],0
mov ah,3h
mov bx,0h
int 10h
mov byte[editc],dl
lea si,[buffer]
input:
mov ah,0h
int 16h
cmp al,9h
jne .next12
jmp tabout
.next12:
cmp al,0dh
je send
cmp al,8h
je back_space
cmp ah,48h
je arrow
cmp ah,50h
je arrow
cmp ah,4bh
je arrow
cmp ah,4dh
je arrow
inc byte[inputlength]
putc al
mov byte[si],al
inc si
jmp input
back_space:
mov ah,03h
mov bh,0h
int 10h
cmp dl,byte[editc]
ja back_cont
jmp input
back_cont:
dec dl
mov ah,02h
int 10h
dec byte[inputlength]
putc 0
call deccur
dec si
mov byte[si],0h
jmp input
arrow:
;ignore
jmp input
tabout:
mov cx,5
tabs:
mov al,0x20
call putchar
mov byte[si],0x20
inc si
loop tabs
jmp input
send:
ret



hang:
pusha
mov bx,100
mul bx
mov cx,ax
hl:
mov bx,cx
hl2:
loop hl2
mov cx,bx
loop hl
popa
ret

clearbuffer:
mov ax,0
clrl:
inc ax
mov byte[si],0
inc si
cmp ax,cx
jnae clrl
ret

_getnum:
mov ax,0
mov al,[si]
sub al,30h
mul cx
ret


b16num:
cmp word[si],0x7830
jne deci
jmp gethex
deci:
add si,4
mov byte[pos],5
mov bx,1
mov cx,0
scl:
xor ax,ax
mov al,byte[si]
cmp al,0
jne addn
dec si
dec byte[pos]
jmp end_addn
addn:
sub al,0x30
mul bx
add cx,ax
dec si
dec byte[pos]
mov ax,bx
mov bx,10
mul bx
mov bx,ax
end_addn:
cmp byte[pos],0
jne scl
ret

gethex:
add si,5
mov byte[pos],4
mov bx,1
mov cx,0
scl1:
xor ax,ax
mov al,byte[si]
cmp al,0
jne addn1
dec si
dec byte[pos]
jmp end_addn1
addn1:
cmp al,0x39
jle sub30
sub al,0x57
jmp otp
sub30:
sub al,0x30
otp:
mul bx
add cx,ax
dec si
dec byte[pos]
mov ax,bx
mov bx,16
mul bx
mov bx,ax
end_addn1:
cmp byte[pos],0
jne scl1
ret




putchar:
mov ah,0eh
int 0x10
ret

print:
lodsb
cmp al,13
jne ntestr
call advline
jmp print
ntestr:
cmp al,0h
je pass02
call putchar
jmp print
pass02:
ret

setcursor:
mov ah,02h
mov bh,0
int 0x10
ret

getcursor:
mov ah,03h
mov bh,0
int 0x10
ret

advcur:
mov ah,03h
mov bh,0
int 10h
inc dl
ifreg dl,80
inc dh
mov dl,0
endif
mov ah,02h
int 10h
ret

deccur:
mov ah,03h
mov bh,0
int 10h
dec dl
mov ah,02h
int 10h
ret

advline:
mov ah,03h
mov bh,0
int 10h
inc dh
mov dl,0
mov ah,02h
int 10h
ret 

setpalette:
mov dx,3c8h
out dx,al
mov dx,3c9h
mov al,bh
out dx,al
mov al,bl
out dx,al
mov al,cl
out dx,al
ret

reset_pic:
push ax
mov al,0x20
out 0x20,al
pop ax
ret

getkey:
mov ah,1
mov al,0
int 16h
jz no_key
mov byte[key],al
mov ax,0
int 16h
jmp end_drv
no_key:
mov byte[key],0
end_drv:
ret



set_interrupt:
mov ax,0       
mov es,ax
mov al,[intr]    
mov bl,4h       
mul bl          
mov bx,ax
mov word[es:bx],si
add bx,2   
mov ax,cs     
mov word[es:bx],ax
ret



print_num:
mov byte[uzero],0
mov bx,10000
mov dx,0
div bx
call numchar
mov ax,dx
mov bx,1000
mov dx,0
div bx
call numchar
mov ax,dx
mov bx,100
mov dx,0
div bx
call numchar
mov ax,dx
mov bx,10
mov dx,0
div bx
call numchar
mov ax,dx
call numchar
cmp byte[uzero],0
jne not_zero
putc '0'
not_zero:
ret


numchar:
cmp al,0
jne pnum
cmp byte[uzero],0
je printnut
add al,0x30
call putchar
jmp numchar_end
printnut:
jmp numchar_end 
pnum:
add al,0x30
call putchar
mov byte[uzero],1
numchar_end:
ret

print_num_hex:
pusha
printf hexd
popa
mov byte[uzero],0
mov bx,4096
mov dx,0
div bx
call numchar2
mov ax,dx
mov bx,256
mov dx,0
div bx
call numchar2
mov ax,dx
mov bx,16
mov dx,0
div bx
call numchar2
mov ax,dx
call numchar2
cmp byte[uzero],0
jne not_zero1
putc '0'
not_zero1:
ret

numchar2:
cmp al,0
jne pnum2
cmp byte[uzero],0
je printnut2
call puthex
jmp numchar2_end
printnut2:
jmp numchar2_end 
pnum2:
call puthex
mov byte[uzero],1
numchar2_end:
ret

puthex:
cmp al,10
jl normprint
add al,0x37
call putchar
ret
normprint:
add al,0x30
call putchar
ret


ttime db "Task time slice: ",0
ttime_suf db " milliseconds",0
cursor dw 0
sterr db "Task identification: No such task.",0
t0 db "Enter _main time slice:",0
t1 db "Enter _btsk time slice:",0
t2 db "Enter _debug time slice:",0
task_time dw 3
mult dw 0
hexd db "0x",0
pmk db "Commandline Interface",0
wv dd 0
tskntr db " <Program execution task: No response..>",0
startcmd:
cmdmem db "Kernel strings: ",0
sttt db "set_task_time",0
gotoc db ".goto",0
debugcmd db "debug",0
dispdata db ".displaydata",0
in_port db ".receive",0
exec db ".execute",0
outp db ".send",0
setport db ".port",0
clear_p db ".clearall",0
clear_data db ".cleardata",0
prog_cnt db ".loc",0
p_new db ".point",0
dispmem db "displaymem",0
dispprog db ".displayprogram",0
exit db "exit",0
help db "help",0
endcmd:
err db "No such command.",0
inp db "Input:",0
msg db "abstractor_main<<",0
program_buffer times 1024 db 0
data_buffer times 256 db 0
dmem db "Displaying data memory",0
pmem db "Program memory:",0
mems db "Displaying memory: ",0
start_offset dw 0
end_offset   dw 0
errsp db "Invalid address",0
pat db "Program pointer:",0
program_loc dw 0
cur_port dw 0
ep db "  <Program execution starts>",0
pt db "  <Program ended>",0
clk db 0
main_state  dw 0,0,0,0,0,0,1
btsk_state  dw 0,0,0,0,0,0,1
debug_state dw 0,0,0,0,0,0,1
_msg db 0,0,0
buffer times 255 db 0
editc db 0
inputlength db 0
pos db 0
intr db 0
uzero db 0
key db 0
axd db "ax: ",0
bxd db "bx: ",0
cxd db "cx: ",0
dxd db "dx: ",0
sid db "si: ",0
spd db "sp: ",0





